#include "bootloader_receive_function.h"
#include "DSP28x_Project.h"   // DSP281x Examples Include File
#include "stream_cipher.h"


volatile unsigned char g_rx_buffer[MAX_PROTOCOL_FRAME_LEN]={0};// 接收缓冲区
volatile unsigned int g_rx_byte_count = 0;
volatile bool g_frame_ready = false;

Uint32 g_expected_data_size=0;     // 期望的总数据包大小 (由CMD_DATA_TRANSFER_COMPLETE命令设置)
Uint32 g_received_data_count=0;    // 已接收的数据字节总数

const unsigned char my_secret_key[16] = {
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
    0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
// --- 16位和校验计算函数 ---
// 传入数据指针和长度，计算并返回16位和校验值
static unsigned int calculate_checksum(const unsigned char *data, unsigned int length)
{
    unsigned int sum = 0;
    unsigned int i;

    for (i = 0; i < length; i++)
    {
        sum += data[i]; // 简单地累加所有字节
    }
    return sum; // 返回16位和
}

// --- 发送响应函数 ---
// 构建并发送从机响应帧
static void send_response(unsigned char command, unsigned char status)
{
    unsigned char tx_buffer[COMMAND_FRAME_LEN];
    volatile unsigned int checksum=0;

    tx_buffer[0] = PROTOCOL_START_BYTE; // 起始字节
    tx_buffer[1] = COMMAND_FRAME_LEN;   // 长度
    tx_buffer[2] = command;             // 响应命令
    tx_buffer[3] = status;              // 状态 (0x00: 成功, 0xFF: 错误/重发)
    tx_buffer[4] = 0x00;                // 保留
    tx_buffer[5] = 0x00;                // 保留

    // 计算校验和，范围从tx_buffer[0]到tx_buffer[5]
    checksum = calculate_checksum(tx_buffer, COMMAND_FRAME_LEN - 2); // 排除校验字节进行计算

    tx_buffer[6] = (unsigned char)(checksum & 0xFF);         // 校验低字节
    tx_buffer[7] = (unsigned char)((checksum >> 8) & 0xFF);  // 校验高字节
    scia_msg(tx_buffer,COMMAND_FRAME_LEN);
    // 通过SCI发送整个响应帧
 //   Sci_sendData(tx_buffer, COMMAND_FRAME_LEN); // 假设 Sci_sendData 实现了发送多个字节
}

// --- 接收单个字节带超时函数 ---
// 从SCI接收一个字节，并带有超时机制 (与之前相同)
static BootloaderStatus receive_byte_timeout(unsigned char *byte_data, unsigned int timeout_ms)
{
    volatile unsigned int timeout_counter = 0;
    const unsigned int timeout_limit = timeout_ms * 1000; // 假设每毫秒计数1000次

    while (SciaRegs.SCIFFRX.bit.RXFFST != 1) // 假设 SciaRegs.SCIFFRX.bit.RXFIFST=1有数据可读
    {
        if (timeout_counter++ > timeout_limit)
        {
            return BOOT_ERR_RX_TIMEOUT; // 超时
        }
        // 适当的延时或空循环
        DELAY_US(1); // 假设有一个微秒延时函数
    }
    *byte_data = SciaRegs.SCIRXBUF.all; // 假设 Sci_readByte() 读取一个字节
    return BOOT_SUCCESS;
}

static unsigned int frame_len=0;
// --- 核心数据接收函数 ---
// 这是主函数或中断服务例程中调用的核心接收函数
BootloaderStatus Bootloader_ReceiveData(void)
{
//    unsigned char rx_byte;
//    unsigned int received_checksum;
//    unsigned int calculated_checksum;
//    unsigned int i;
// 5. 根据命令字节处理数据 (这部分逻辑与之前相同)
    FLASH_ST EraseStatus;
    switch (g_rx_buffer[2]) // g_rx_buffer[2] 是命令字节
    {
        case CMD_START_UPGRADE: // 0x01 开始升级
            // 协议: eb 08 01 00 00 00 checksum
            if (frame_len == COMMAND_FRAME_LEN &&
                g_rx_buffer[3] == 0x00 && g_rx_buffer[4] == 0x00 && g_rx_buffer[5] == 0x00)
            {
                // 可以在这里执行APP区擦除等初始化操作
                // ......
                Flash_Erase(SECTORF,&EraseStatus);
                send_response(RSP_ACK_START_UPGRADE, RSP_SUCCESS); // 确认可以升级
                g_received_data_count = 0; // 重置已接收数据计数
                g_expected_data_size = 0;  // 重置期望数据大小
                frame_len=0;
                return BOOT_SUCCESS;
            }
            else
            {
                send_response(RSP_ACK_START_UPGRADE, RSP_ERROR); // 命令格式错误
                frame_len=0;
                return BOOT_ERR_UNKNOWN_COMMAND;
            }
        case CMD_TRANSMIT_DATA: // 0x02 传输数据
            // 协议: eb 85 02 (128字节数据) checksum
            if (frame_len == FIXED_DATA_FRAME_LEN)
            {
                Uint16 *flash_target_address = (Uint16 *)0x3EC000;
                // 将128字节的数据写入FLASH (这里需要根据实际FLASH驱动实现)
                // 假设有一个函数 Flash_WriteData(address, data_buffer, length)
                // 计算写入的FLASH地址
                // unsigned long flash_address = APP_START_ADDRESS + g_received_data_count;
                //Flash_WriteData(flash_address, &g_rx_buffer[3], 128); // 数据从g_rx_buffer[3]开始
                stream_cipher_process(&g_rx_buffer[3], OTA_DATA_LEN, my_secret_key, 16);
                Program_FlashAdder(flash_target_address,(Uint16 *)&g_rx_buffer[3],128);
                //Flash_Program(flash_target_address,(Uint16 *)&g_rx_buffer[3],128,&ProgramStatus);
                g_received_data_count += (frame_len-5); // 更新已接收数据计数
                send_response(RSP_ACK_TRANSMIT_DATA, RSP_SUCCESS); // 确认数据正确
                frame_len=0;
                return BOOT_SUCCESS;
            }
            else
            {
                send_response(RSP_ACK_TRANSMIT_DATA, RSP_ERROR); // 命令格式错误
                frame_len=0;
                return BOOT_ERR_UNKNOWN_COMMAND;
            }
        case CMD_DATA_TRANSFER_COMPLETE: // 0x03 数据包发送完毕
            // 协议: eb 08 03 (数据包大小,2字节) 00 checksum
            if (frame_len == COMMAND_FRAME_LEN && g_rx_buffer[0] == 0xeb)
            {
                // 获取主机发送的总数据包大小
                g_expected_data_size = ( ((Uint32)g_rx_buffer[5] << 16) | \
                                         ((Uint32)g_rx_buffer[4] << 8)  | \
                                         ((Uint32)g_rx_buffer[3]) );
                if (g_received_data_count == g_expected_data_size)
                {
                    // 数据包完整，可以跳转到APP
                    // 可以在这里执行FLASH校验等操作
                    // ......
                    send_response(RSP_ACK_DATA_TRANSFER_COMPLETE, RSP_SUCCESS); // 确认数据包完整
                    frame_len=0;
                    return BOOT_SUCCESS;
                }
                else
                {
                    // 数据包不完整，请求重新升级
                    // 从机擦除APP区，进入boot重新等待升级命令
                    // Flash_EraseAppArea(); // 假设有擦除APP区域的函数
                    send_response(RSP_ACK_DATA_TRANSFER_COMPLETE, RSP_ERROR);
                    frame_len=0;
                    return BOOT_ERR_INTERNAL; // 返回一个指示需要重新升级的错误
                }
            }
            else
            {
                send_response(RSP_ACK_DATA_TRANSFER_COMPLETE, RSP_ERROR); // 命令格式错误
                frame_len=0;
                return BOOT_ERR_UNKNOWN_COMMAND;
            }
        default:
            break;
    }
   // }
    return BOOT_SUCCESS;
}

/**
 * @brief 更新应用程序的函数
 *
 * 该函数用于更新应用程序。它不断地从SCI接收缓冲区读取数据，并准备将其写入闪存中。
 *
 * @return Uint16 返回状态码，成功返回0，失败返回非0值
 * bit0 bit1 bit2 bit3 bit4  bit5 bit6  bit7      bit8       bit9        bit10    bit11   bit12 bit13 bit14
 * 0xEB 0X90 0x55 0xAA 命令1 命令2 长度H 长度L 地址[31:24]  地址[23:16] 地址[15:8] 地址[7:0]
 * 命令0：0x00 不升级 命令1：0x01 升级 命令2：0x02 擦除
 */
Uint16 APP_Updata(void)//APP升级函数
{
    int16 Job_Status=0;
   //   Uint16 data_len=0,rxdata_err=0,first_addr=0,i=0,j=0,status=0,updata_err=0;
   //   Uint16 *flash_addr;
   //Uint32 start_addr=0,rx_len=0;
   while (1)
   {
       switch(Job_Status)
       {
           case 0://等待接收数据
               if(rx_buffer_count >0 )
               {
                   // 从环形缓冲器中读取一个字节到当前帧缓冲器
                   g_rx_buffer[frame_len++]= rx_buffer[rx_buffer_read_idx];
                   rx_buffer_read_idx = (rx_buffer_read_idx + 1) % RX_BUFFER_SIZE; // 更新读取索引
                   rx_buffer_count--; // 减少缓冲器中数据量计数
               }
               break;
           case 1://接收数据确认
               // 检查帧起始符 (0xeb)、帧总长度是否与 g_rx_buffer[1] 匹配、以及最小帧长度 (8字节)
               if((g_rx_buffer[0] == 0xeb) && (g_rx_buffer[1] == frame_len) && (frame_len >= 8))
               {
                   // 如果帧确认成功，调用数据处理函数
                   Bootloader_ReceiveData(); // 假设此函数会处理 g_rx_buffer 中的完整帧数据
               }
               break;
           default: // 处理 Job_Status 变量的任何非预期值
               Job_Status = 0;
               frame_len = 0;
               break;
       }
       if(Job_Status == 1)
       {
           Job_Status = -1;
       }
       Job_Status++;
   }
}
/**
 * @brief 检查应用是否需要更新
 *
 * 该函数检查特定地址上的标志位，以确定应用是否需要更新。
 *
 * @return 无返回值
 */
void app_updata_chk(void)
{
//   Uint16 Status = 0;
//   Uint32 *Flag_ptr;
//   Uint16 app_updata_chk_flag = 0;
//
//   Flag_ptr = APP_UPDATA_FALG_ADDR; //需要升级的地址
//   app_updata_chk_flag = *Flag_ptr;
//   if(app_updata_chk_flag != APP_UPDATA_SUCCESS) //需要升级
//   {
//       Status=APP_Updata();
//   }
}
/**
 * @brief 处理混合数据
 *
 * 处理从某种设备读取的混合数据，包括长度调整和地址赋值。
 *
 * @param data 输入的混合数据指针
 * @param addr 地址指针，用于存储处理后的地址
 *
 * @return 调整后数据的长度（以字为单位）
 */
Uint16 AppHybridData_Deal(Uint16 *data, Uint32 *addr)
{
   int i = 0;
   Uint16 len = data[6];
   len |= (len << 8) | data[7];
   *addr = data[8];
   *addr = (*addr << 16) | data[9];

   len = len - 2;
   for (i = 0; i < len; i++)
   {
      data[i] = data[i + 8];
   }
   return len;
}
/**
 * @brief 将数据写入Flash存储器
 *
 * 将给定的数据写入到指定的Flash地址，并进行验证以确保数据正确写入。
 *
 * @param startaddr 指向Flash起始地址的指针
 * @param data 指向要写入的数据的指针
 * @param len 要写入的数据长度
 *
 * @return 返回操作状态码。如果操作成功，则返回STATUSS_SUCCESS；否则返回相应的错误码。
 */
Uint16 Program_FlashAdder(Uint16 *startaddr, Uint16 *data, Uint16 len) // дflash
{
   Uint16 Status = 0;
   FLASH_ST ProgramStatus;
   Flash_Program(startaddr,data,len,&ProgramStatus);
   //Status = Flash_Program(startaddr, data, len);
   if (Status != STATUSS_SUCCESS)
   {
      return Status;
   }
   Status = Flash_Verify(startaddr, data, len,&ProgramStatus);
   if (Status != STATUSS_SUCCESS)
   {
      return Status;
   }
   return STATUSS_SUCCESS;
}
//===========================================================================
// No more.
//===========================================================================


